#ifndef STEREO_VIEW_H
#define STEREO_VIEW_H

#include <cstdlib>
#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
#include <cassert>


#if defined(_WIN32)
#include <GL/glew.h>
#endif
#include <GL/glut.h>

#define DEBUG_STEREO 0

/*
* Much of this code was inspired by Lab10 which covered stereo viewing.
*
* This class was intended to be responsible for performing all of the transforms
* but has been modified to act as data holders for us to use for stereo vision.
*/

namespace stereo{
	class StereoView
	{
	public:
		int pixelsWidth[2];
		int pixelsHeight[2];

		//Limits for viewing volume
		GLfloat zNear, zFar;

		//Point where the viewing frustra overlap
		float vergence;

		//Width of the frustra at the vergence plane
		float width;

		//Separation between the two views
		float separation;

		//Inverted aspect ratio for each view
		float aspectRatio[2];

		StereoView();
		StereoView(float _zNear, float _zFar, int _width, int _height);

		//get our frustums
		void getLeftFrustum(float& _left, float& _right, float& _bottom, float& _top,
							float& _near, float& _far);
		void getRightFrustum(float& _left, float& _right, float& _bottom, float& _top,
							 float& _near, float& _far);
		
		//set the respective frustum
		void setGLFrustum( int _camera );

		void setSeparation(float _separation);
		void addSeparation(float _add);

		void moveVergence( float _t );

		inline GLfloat getSeparation();
		inline GLfloat getNear();
		inline GLfloat getFar();

		inline void setNear(float _near);
		inline void setFar(float _far);

		inline void getWindowSize(int _camera, int& _width, int& _height);
		inline void setWindowSize(int _camera, int _width, int _height);
		inline void updateAspect();
	};

	GLfloat StereoView::getSeparation(){
		return static_cast<GLfloat>(separation);
	}

	GLfloat StereoView::getNear(){
		return zNear;
	}

	GLfloat StereoView::getFar(){
		return zFar;
	}

	void StereoView::setNear(float _near){
		zNear = _near;
	}

	void StereoView::setFar(float _far){
		zFar = _far;
	}

	void StereoView::getWindowSize(int _camera, int& _width, int& _height){
		assert( _camera >= 0 && _camera <= 1);
		_width = pixelsWidth[_camera];
		_height = pixelsHeight[_camera];
		return;
	}

	void StereoView::setWindowSize(int _camera, int _width, int _height){
		assert( _camera >= 0 && _camera <= 1);
		pixelsWidth[_camera] = _width;
		pixelsHeight[_camera] = _height;
		return;
	}

	//An approach to keeping windows consistent-- max window height determines vertical strech
	void StereoView::updateAspect(){
		if(pixelsHeight[1] < pixelsHeight[0]){
			aspectRatio[1] = static_cast<float>(pixelsHeight[1])/pixelsHeight[0];
		} else {
			aspectRatio[0] = static_cast<float>(pixelsHeight[0])/pixelsHeight[1];
		}
	}
}

#endif